var iconSmallThread = `<svg width="24" height="24" class="crayons-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17 13l-5 6-5-6h3.125c0-3.314 2.798-6 6.25-6 .17 0 .34.006.506.02-1.787.904-3.006 2.705-3.006 4.78V13H17z" /></svg>`;

/**
 *
 * A function that triggers all the interactivity when a page with comments are loaded.
 * It calls sub-functions to define functionality for fetching async info, and attaching
 * event listeners related to rich UI interaction and form submission.
 *
 * When comment reaction data needs to be fetched and how we make those choices:
 * When no logged in user only need to fetch reaction numbers if there has been recent comment activity.
 * If no recent comments, we do not need the precision of fetching latest counts async. Static value is almost certainly good enough.
 * Always fetch when user is logged in because we need state of whether the user has reacted.
 *
 * @function initializeCommentsPage
 */

function initializeCommentsPage() {
  if (document.getElementById('comments-container')) {
    toggleCodeOfConduct();
    var userStatus = document.body.getAttribute('data-user-status');
    var commentableId = document.getElementById('comments-container').dataset.commentableId;
    var commentableType = document.getElementById('comments-container').dataset.commentableType;
    var hasRecentCommentActivity = document.getElementById('comments-container').dataset.hasRecentCommentActivity;
    commentableIdList = commentableId.split(",");

    if (userStatus === 'logged-in' || hasRecentCommentActivity !== 'false') {
      var f = (function() {
        for (var i = 0; i < commentableIdList.length; i++) {
          (function(i){
            var ajaxReq;
            ajaxReq = new XMLHttpRequest();
            ajaxReq.onreadystatechange = function () {
              if (ajaxReq.readyState === XMLHttpRequest.DONE) {
                var responseObj = JSON.parse(ajaxReq.response);
                var reactions = responseObj.reactions;
                var allNodes = document.getElementsByClassName('single-comment-node');
                var publicReactionCounts = responseObj.public_reaction_counts;
                for (var i = 0; i < reactions.length; i++) {
                  var buttForComment = document.getElementById('button-for-comment-' + reactions[i].reactable_id);
                  if (buttForComment) {
                    buttForComment.classList.add('reacted');
                    buttForComment.setAttribute('aria-pressed', 'true')
                  }
                }
                for (var i = 0; i < publicReactionCounts.length; i++) {
                  var buttForComment = document.getElementById('button-for-comment-' + publicReactionCounts[i].id);
                  if (buttForComment) {
                    var reactionsCountWrapper = buttForComment.querySelector('.reactions-count');
                    var reactionsLabelWrapper = buttForComment.querySelector('.reactions-label');
                    if (publicReactionCounts[i].count > 0 && reactionsLabelWrapper) {

                      if (publicReactionCounts[i].count > 1) {
                        reactionsLabelWrapper.innerHTML = `&nbsp;${I18n.t('core.like').toLowerCase()}s`;
                      } else {
                        reactionsLabelWrapper.innerHTML = `&nbsp;${I18n.t('core.like').toLowerCase()}`;
                      }

                      reactionsCountWrapper.id = 'reactions-count-' + publicReactionCounts[i].id;
                      reactionsCountWrapper.innerHTML = publicReactionCounts[i].count;
                      reactionsCountWrapper.classList.remove("hidden");
                    } else {
                      reactionsCountWrapper.classList.add("hidden");
                      reactionsCountWrapper.innerHTML = '0';
                    }

                    if (!buttForComment.classList.contains("reacted")) {
                      buttForComment.setAttribute('aria-pressed', 'false');
                    }
                  }
                }

                for (var i = 0; i < allNodes.length; i++) {
                  if (allNodes[i].dataset.commentAuthorId == responseObj.current_user.id) {
                    allNodes[i].dataset.currentUserComment = "true";
                    var path = allNodes[i].dataset.path;
                    var userActionsEl = allNodes[i].querySelector('.current-user-actions');
                    var buttEl = document.getElementById('button-for-comment-' + allNodes[i].dataset.commentId);
                    if (userActionsEl && buttEl) {
                      userActionsEl.innerHTML = `<li><a href="${ path }/edit" class="crayons-link crayons-link--block" aria-label="Edit this comment">Edit</a></li>
                                                <li><a data-no-instant href="${ path }/delete_confirm" class="edit-butt crayons-link crayons-link--block" aria-label="Delete this comment">Delete</a></li>`
                      userActionsEl.classList.remove('hidden');
                    }
                  }
                }
              }
            };

            ajaxReq.open("GET", "/reactions?commentable_id=" + commentableIdList[i] + "&commentable_type=" + commentableType, true);
            ajaxReq.send();
          })(i);
        }
      })();
    }

    var butts = document.getElementsByClassName('reaction-button');
    for (var i = 0; i < butts.length; i++) {
      var butt = butts[i];
      butt.onclick = function (event) {
        var thisButt = this;
        event.preventDefault();
        sendHapticMessage('medium');
        var userStatus = document.body.getAttribute('data-user-status');
        if (userStatus === 'logged-out') {
          showLoginModal({ referring_source: 'comment', trigger: 'like' });
          return;
        }

        thisButt.classList.add('reacted');
        thisButt.disabled = true;

        function successCb(response) {
          var reactionCount = thisButt.querySelector('.reactions-count');
          var reactionLabel = thisButt.querySelector('.reactions-label');
          if (response.result === 'create') {
            thisButt.classList.add('reacted');
            thisButt.setAttribute('aria-pressed', 'true');
            if (reactionCount) {
              reactionCount.innerHTML = parseInt(reactionCount.innerHTML) + 1;
              reactionCount.classList.remove("hidden");
              if(parseInt(reactionCount.innerHTML) == 1) {
                reactionLabel.innerHTML = "&nbsp;like"
              } else if(parseInt(reactionCount.innerHTML) > 1) {
                reactionLabel.innerHTML = "&nbsp;likes"
              }
            }
          } else {
            thisButt.classList.remove('reacted');
            thisButt.setAttribute('aria-pressed', 'false');
            if (reactionCount) {
              reactionCount.innerHTML = parseInt(reactionCount.innerHTML) - 1;
              if(parseInt(reactionCount.innerHTML) == 0) {
                reactionCount.classList.add("hidden");
                thisButt.classList.remove('crayons-btn--icon-left');
                thisButt.classList.add('crayons-btn--icon');
                reactionLabel.innerHTML = ""
              }
            }
          }
        }
        var formData = new FormData();
        formData.append('reactable_type', 'Comment');
        formData.append('reactable_id', thisButt.dataset.commentId);
        getCsrfToken()
          .then(sendFetch('reaction-creation', formData))
          .then(function (response) {
            thisButt.disabled = false;
            if (response.status === 200) {
              response.json().then(successCb);
            } else {
              showModalAfterError({
                response,
                element: 'reaction',
                action_ing: 'making',
                action_past: 'made',
              });
            }
          });
      };
    }
    var replyButts = document.getElementsByClassName('toggle-reply-form');
    for (var i = 0; i < replyButts.length; i++) {
      var butt = replyButts[i];
      butt.onclick = function (event) {
        event.preventDefault();
        if (event.target.classList.contains("thread-indication")) {
          return false;
        } else {
          var userStatus = document.body.getAttribute('data-user-status');
          if (userStatus == 'logged-out') {
            showLoginModal({ referring_source: 'comment', trigger: 'reply' });
            return;
          }
          var parentId = event.target.closest('.comment').dataset.commentId;
          var waitingOnCSRF = setInterval(function () {
            var metaTag = document.querySelector("meta[name='csrf-token']");
            if (metaTag) {
              clearInterval(waitingOnCSRF);
              commentWrapper = event.target.closest('.comment__details');
              commentWrapper.classList.add("replying");
              commentWrapper.innerHTML += buildCommentFormHTML(commentableId, commentableType, parentId);
              initializeCommentsPage();

              setTimeout(function () {
                commentWrapper.getElementsByTagName('textarea')[0].focus();
              }, 30);
            }
          }, 1);
        };
        return false;
      }
    }

    if (document.getElementById('new_comment')) {
      document.getElementById('new_comment').addEventListener('submit', handleCommentSubmit);
    }
  }
  listenForDetailsToggle();

  handleHiddenComments(commentableType);
}

function toggleCodeOfConduct() {
  var user = userData();
  if (!user) {
    return;
  }
  var codeOfConduct = user.checked_code_of_conduct
  var checkboxWrapper = document.getElementById('toggle-code-of-conduct-checkbox');
  if (checkboxWrapper && !codeOfConduct) {
    checkboxWrapper.innerHTML = '<input type="checkbox" name="checked_code_of_conduct" class="checkbox" required/>\
                                  <label for="checked_code_of_conduct">I\'ve read the <a href="/code-of-conduct">code of conduct</a></label>'
  }
}

function handleCommentSubmit(event) {
  event.preventDefault();
  var form = event.target;
  form.classList.add('submitting');
  var textarea = form.getElementsByClassName('comment-textarea')[0];
  if (textarea) {
    textarea.style.height = null;
    textarea.blur();
  }
  var parentComment = document.getElementById("comment-node-" + event.target.dataset.commentId);

  // as there can be multiple forms rendered in the comments, we need to use querySelector to find descendants
  var commentParentId = form.querySelector("#comment_parent_id");
  var body = JSON.stringify({
    comment: {
      body_markdown: form.getElementsByTagName("textarea")[0].value,
      commentable_id: form.querySelector("#comment_commentable_id").value,
      commentable_type: form.querySelector("#comment_commentable_type").value,
      parent_id: commentParentId ? commentParentId.value : null,
    }
  });

  getCsrfToken()
    .then(sendFetch('comment-creation', body))
    .then(function (response) {
      if (response.status === 200) {
        response.json().then(function (newComment) {
          var newNode = document.createElement('div');
          newNode.innerHTML = buildCommentHTML(newComment);
          var docBody = document.body

          var userData = JSON.parse(docBody.getAttribute('data-user'))
          userData.checked_code_of_conduct = true;

          docBody.dataset.user = JSON.stringify(userData);

          var checkbox = form.getElementsByClassName('code-of-conduct')[0]
          if (checkbox) {
            checkbox.innerHTML = ""
          }

          var mainCommentsForm = document.getElementById("new_comment");
          if (parentComment) {
            handleFormClose(event);
            if (newComment.depth > 3) {
              var replyTrigger = parentComment.getElementsByClassName("toggle-reply-form")[0];
              var threadIndicator = `<span class="fs-s inline-flex items-center fs-italic color-base-50 pl-1">${ iconSmallThread }Thread</span>`;
              replyTrigger.classList.replace("inline-flex", "hidden");
              replyTrigger.parentNode.innerHTML += threadIndicator;
            }
            var actionsNode = parentComment.getElementsByClassName("comment__inner")[0];
            actionsNode.parentNode.insertBefore(newNode, actionsNode.nextSibling);
          }

          else if (mainCommentsForm) {
            var mainCommentsForm = document.getElementById("new_comment");
            mainCommentsForm.classList.remove("submitting");
            mainCommentsForm.classList.remove('preview-open');

            const commentInputs = [...form.getElementsByClassName("comment-textarea")]
            commentInputs[0].closest('.comment-form').classList.remove('comment-form--initiated');

            // Clearing out all comment textboxes and resetting their height because
            // there is an additional one generated by the comment
            // mention auto-complete component
            commentInputs.forEach(input => {
              input.value = newComment.comment_template || "";
              input.style.height = null;
            });

            const preview = document.getElementById("preview-div");
            const togglePreview = document.querySelector('.preview-toggle');
            preview.innerHTML = "";
            togglePreview.innerHTML = "Preview";
            const container = document.getElementById("comment-trees-container");
            container.insertBefore(newNode, container.firstChild);
          }
          else if (document.getElementById("notifications-container")) {
            var newDiv = document.createElement("span")
            newDiv.innerHTML = '<div class="crayons-notice align-center p-2 m-2 crayons-notice--success reply-sent-notice reply-sent-notice" aria-live="polite">Reply sent — <a href="' + newComment.url + '">Check it out</a></div>'
            form.replaceWith(newDiv);
          }
          else {
            window.location.replace(newComment.url)
          }
          updateCommentsCount();
          initializeCommentsPage();
          initializeCommentDate();
          activateRunkitTags();
        })
      } else {
        form.classList.remove('submitting');
        showModalAfterError({
          response,
          element: 'comment',
          action_ing: 'posting',
          action_past: 'posted',
        });
        return false;
      }
      return false;
    });
  return false;
}

function handleFocus(event) {
  handleButtonsActivation(event);
  var userStatus = document.body.getAttribute('data-user-status');
  var area = event.target;
  if (userStatus == 'logged-out') {
    event.preventDefault();
    showLoginModal({ referring_source: 'comments', trigger: 'new_comment'});
    area.blur();
  } else {
    var form = event.target.closest(".comment-form");
    if (form) {
      form.classList.add("comment-form--initiated");
    }
    handleSizeChange(event);
    window.Forem.initializeEnhancedCommentTextArea(area);
  }
}

function handleKeyUp(event) {
  handleSizeChange(event);
  handleButtonsActivation(event);
}

// Handler for when Ctrl+Enter OR Command+Enter is pressed
function handleSubmit(event) {
  // Get user details and extract code of conduct & comment count
  var user = userData();
  if (!user) {
    return;
  }

  var codeOfConduct = user.checked_code_of_conduct;
  if (codeOfConduct && event.target.value.trim() !== '') {
    event.target.closest('form').querySelector('button[type="submit"]').click();
  }
}

var ENTER_KEY_CODE = 13;
function handleKeyDown(event) {
  if (window.Forem.Runtime.hasOSSpecificModifier(event) && event.keyCode === ENTER_KEY_CODE) {
    event.preventDefault();
    handleSubmit(event);
  }
}

function handleFormClose(event) {
  // When closing the inline reply form, remove the temporary
  // "replying" state from the correct container. The class is
  // added on `.comment__details` when the reply form is opened,
  // but previously we attempted to remove it from `.inner-comment`,
  // which left the comment in a semi-disabled visual state (e.g.,
  // faded/hidden footer and odd tooltip stacking) until page reload.
  var detailsEl = event.target.closest('.comment__details');
  if (detailsEl) {
    detailsEl.classList.remove('replying');
  }
  event.target.closest('.comment-form').remove();
  initializeCommentsPage();
}

function handleSizeChange(event) {
  var textarea = event.target;
  var oldHeight = parseInt(textarea.style.height.replace('px',''));
  textarea.style.height = textarea.scrollHeight + (textarea.scrollHeight > oldHeight ? 15 : 0) + "px";
}

function handleButtonsActivation(event) {
  var textarea = event.target;
  var commentForm = textarea.closest('.comment-form');
  if (commentForm) {
    var buttons = textarea.closest('.comment-form').getElementsByClassName('js-btn-enable');
    Array.from(buttons).forEach(function(button) {
      button.disabled = textarea.value.length === 0;
    });
  };
}

function validateField(event) {
  // We only need to validate the textarea that is not the comment mention auto-complete component
  const textArea = event.target.form.querySelector('.comment-textarea:not([role=combobox])');

  if (textArea.value === '') {
    event.preventDefault();
    return;
  }
}

function handleChange(event) {
  handleButtonsActivation(event);
}

function generateUploadFormdata(image) {
  var token = document.querySelector("meta[name='csrf-token']").content;
  var formData = new FormData();
  formData.append('authenticity_token', token);
  formData.append('image', image[0]);
  return formData;
}

function updateItemSummaryHtml(item) {
  var itemSummaryContent = item.getElementsByClassName("js-collapse-comment-content")[0];
  var usernames = item.getElementsByClassName("js-comment-username");
  var number = "";
  if (usernames.length > 1) {
    number = " + " + (usernames.length - 1) + " replies"
  }
  var itemUsername = usernames[0].textContent + number
  if (item.open) {
    itemSummaryContent.textContent = "";
  } else {
    itemSummaryContent.textContent = itemUsername;
  }
}

function listenForDetailsToggle() {
  var detailItems = document.querySelectorAll(".js-comment-wrapper");
  for (var i = 0; i < detailItems.length; i++) {
    detailItems[i].addEventListener("toggle", event => {
      var item = event.target;
      updateItemSummaryHtml(item);
    });
  }
}

/**
 * Increment comment, stored in `.js-comments-count`, count by one.
 */
function updateCommentsCount() {
  const commentsCountDiv = document.querySelector(".js-comments-count");

  // if there's nowhere to put the count return early.
  if(!commentsCountDiv) return;

  const commentsCountData = parseInt(commentsCountDiv.dataset.commentsCount, 10) + 1;
  commentsCountDiv.dataset.commentsCount = commentsCountData;
  commentsCountDiv.innerHTML = `(${commentsCountData})`

  const commentsSidebarCountDiv = document.getElementById("reaction-number-comment");
  if (!commentsSidebarCountDiv) return;
  commentsSidebarCountDiv.innerHTML = `${commentsCountData}`;
}

function initializeCommentDate() {
  const commentsDates = document.querySelectorAll('.comment-date time');

  if (commentsDates) {
    addLocalizedDateTimeToElementsTitles(commentsDates, 'datetime');
  }
}

function handleHiddenComments(commentableType){
  const currentUser = userData();
  const commentableAuthorIds = [];
  let coAuthorIds = '';
  if(commentableType === "Article"){
    const articleContainer = document.querySelector('#article-show-container');
    if(articleContainer){
      if (articleContainer.dataset) {
        commentableAuthorIds.push(articleContainer.dataset.authorId);
        coAuthorIds = articleContainer.dataset.coAuthorIds;
        if(coAuthorIds){
          coAuthorIds.split(',').forEach(coAuthorId => {
            commentableAuthorIds.push(coAuthorId);
          });
        }
      }
    }
    else {
      const commentsContainer = document.querySelector('#comments-container');
      if(commentsContainer){
        if(commentsContainer.dataset) {
          commentableAuthorIds.push(commentsContainer.dataset.commentableAuthorId);
          coAuthorIds = commentsContainer.dataset.commentableCoAuthorIds;
          if(coAuthorIds){
            coAuthorIds.split(',').forEach(coAuthorId => {
              commentableAuthorIds.push(coAuthorId);
            });
          }
        }
      }
    }
  } else if(commentableType === "PodcastEpisode"){
    const podCastEpisodeContainer = document.querySelector('.podcast-episode-container');
    if(podCastEpisodeContainer){
      commentableAuthorIds.push(podCastEpisodeContainer.dataset.creatorId);
    }
  }
  if(currentUser && commentableAuthorIds.includes(currentUser.id.toString())){
    collapseCommentsHiddenByCommentableUser();
  }
  else {
    document.querySelectorAll('.element-hidden-by-commentable-user').forEach(element => {
      element.classList.add('hidden');
    })
    document.querySelectorAll('.comment-hidden-by-author-text').forEach(element => {
      element.classList.remove('hidden');
    })
  }
}

function collapseCommentsHiddenByCommentableUser() {
  document.querySelectorAll(".js-comment-wrapper.details-comment-hidden-by-commentable-user").forEach(item => {
    if (item.querySelectorAll('.comment-form').length === 0){
      item.open = false;
      updateItemSummaryHtml(item);
    }
  })
}
